package org.su.generalmvc.core;


import org.su.generalmvc.IModel;
import org.su.generalmvc.jdbc.IDao;
import org.su.generalmvc.render.IRender;
import org.su.generalmvc.validate.Errors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.List;


/**
 * 默认action调用类，每次请求过来都需要new一个该对象，用来处理对应的请求
 * @author yangchuan
 * @since 2012-03-6
 * @version 1.0
 */
public class DefaultActionInvocation implements ActionInvocation,Runnable {



	protected static final Log logger = LogFactory.getLog(DefaultActionInvocation.class);
	
	
	public DefaultActionInvocation(ActionProxy proxy, ServletRequest request,
                                   ServletResponse response) {
		super();
		this.request = request;
		this.response = response;
		init(proxy);
	}


	/**
	 * action代理对象
	 */
	protected ActionProxy proxy;
	
	/**
	 * 拦截器栈
	 *//*
	protected Iterator<Interceptor> interceptors;*/
	
	protected List<Interceptor> interceptorList;
	
	/**
	 * 记录拦截器的栈长
	 */
	private int count;
	/**
	 * 当前栈指针
	 */
	private int step;
	
	/**
	 * action参数对象
	 */
	private Object[] args = null;
	
	private ServletRequest request;
	
	private ServletResponse response;
	
	
	/**
	 * 获取web请求对象
	 * @return web请求对象
	 */
	public ServletRequest getRequest() {
		return request;
	}

	/**
	 * 获取web相应对象
	 * 
	 * @return web响应对象
	 */
	public ServletResponse getResponse() {
		return response;
	}



	/**
	 * 调用action处理
	 * @return 返回调用action的结果信息（可能是vm地址或json字串）
     * @throws javax.naming.ConfigurationException If no result can be found with the returned code
     */
    public Object invoke() throws Exception {
        Object resultCode = null;
         
        	/**
        	 * 依次调用拦截器
        	 */
            /*if (interceptors.hasNext()) {
                final Interceptor interceptor = interceptors.next();*/
            if(step < count){
            	final Interceptor interceptor = interceptorList.get(step++);
                try {
                       resultCode = interceptor.intercept(DefaultActionInvocation.this);
                 }
                finally {
                }
            } else {
                resultCode = invokeActionOnly();
            }
            
         return  resultCode;
    }

    public static void main(String[] args) {
    	int i=0;
		System.out.println(i++);
	}
    
    /**
     * 处理web请求
     */
    public void parseRequest(){
    	IModel obj = null;
    	Object result = null;
    	try{
			result = invoke();
    		obj = getModel();
    		IRender render = proxy.getActionConfig().getRender();
    		render.render(obj, result,proxy.getActionConfig().getDefaultViewPath(), request, response);
    	}catch(Exception e){
    		logger.error(e.getMessage(), e);
    		if(getModel() != null){
   			 	obj = getModel();
    		}
    		if(obj == null){
    			obj = new Errors();
    		}
    		obj.put("exception", e);
    		
    		IRender render = proxy.getActionConfig().getExcptionRender();
    		try {
				render.render(obj, result, proxy.getActionConfig().getDefaultViewPath(),request, response);
			} catch (IOException e1) {
				logger.error(e1);
			}
    	}
    }

    /**
     * 调用实际的action方法
     * @return 返回调用结果，可能是页面跳转的地址
     */
	@Override
	public Object invokeActionOnly() throws Exception {
		return proxy.execute(args);
	}


	/**
	 * 初始化action调用环境，生成新的迭代器
	 */
	@Override
	public void init(ActionProxy proxy) {
		this.proxy = proxy;
		interceptorList = proxy.getActionConfig().getInterceptors();
		count = interceptorList.size();
		step = 0;
	}


	/**
	 * @return 获取action代理对象
	 */
	public ActionProxy getProxy() {
		return proxy;
	}


	/**
	 * @return 获取action的参数值
	 */
	public Object[] getArgs() {
		return args;
	}


	/**
	 * 设置action的参数值
	 */
	public void setArgs(Object[] args) {
		this.args = args;
	}
	
	/**
	 * @return 返回结果数据模型
	 */
	@Override
	public IModel getModel() {
		return (IModel)request.getAttribute(IModel.MODEL_DATA);
	}
	
	/**
	 * 获取请求中的dao对象
	 * @return 返回当前调用的dao对象
	 */
	@Override
	public IDao getDao(){
		return (IDao)request.getAttribute(IDao.DAO_KEY);
	}

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p/>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        parseRequest();
    }

    /**
	 * 获得当前userSession对象。
	 * @return
	 *//*
	@Override
	public Object getUserSession(){
		return this.getRequest().getSession().getAttribute(IUserSession.USER_SESSION);
	}*/
}
